package com.feather.common.thoughtworks.xstream;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;

/**
 * @author flogyin
 */
public class XStreamWrapper {
	private XStream	xStream	= new XStream();
	private String	encoding;

	public XStreamWrapper() {
		this.xStream = new XStream();
	}

	public XStreamWrapper(String encoding) {
		if (encoding != null) {
			this.xStream = new XStream(new DomDriver(encoding));
			this.encoding = encoding;
		} else {
			this.xStream = new XStream();
		}
	}

	public Object input(InputStream is) {
		try {
			return this.xStream.fromXML(is);
		} finally {
			try {
				is.close();
			} catch (IOException ex) {

			}
		}
	}

	public Object input(Reader reader) {
		try {
			return this.xStream.fromXML(reader);
		} finally {
			try {
				reader.close();
			} catch (IOException ex) {

			}
		}
	}

	public void output(Object obj, OutputStream os) {
		this.xStream.toXML(obj, os);
	}

	public void output(Object obj, Writer w) {
		this.xStream.toXML(obj, w);
	}

	public String toChars(Object obj) throws IOException {
		StringWriter sw = new StringWriter();
		try {
			String header = "";
			if (this.encoding != null) {
				header = "<?xml version=\"1.0\" encoding=\"" + encoding + "\"?>\n";
			}
			this.xStream.toXML(obj, sw);

			String chars = sw.toString();
			if (header == null || chars == null) {
				return chars;
			}
			return header + chars;
		} finally {
			try {
				if (sw != null)
					sw.close();
			} catch (IOException ex) {
				throw ex;
			}
		}
	}

	public byte[] toBytes(Object obj) throws IOException {
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		OutputStreamWriter osw = new OutputStreamWriter(baos);
		try {
			byte[] header = null;
			if (this.encoding != null) {
				String x = "<?xml version=\"1.0\" encoding=\"" + encoding + "\"?>\n";
				header = x.getBytes();
			}
			this.xStream.toXML(obj, baos);

			byte[] bytes = baos.toByteArray();
			if (header == null || bytes == null) {
				return bytes;
			}
			byte[] m = new byte[header.length + bytes.length];
			System.arraycopy(header, 0, m, 0, header.length);
			System.arraycopy(bytes, 0, m, header.length, bytes.length);
			return m;
		} finally {
			try {
				if (osw != null)
					osw.close();
			} catch (IOException ex) {
				throw ex;
			}
			try {
				baos.close();
			} catch (IOException ex) {
				throw ex;
			}
		}
	}

	public Object toObject(String chars) throws IOException {
		StringReader sr = new StringReader(chars);
		try {
			return this.xStream.fromXML(sr);
		} finally {
			sr.close();
		}
	}

	public Object toObject(byte[] bytes) throws IOException {
		ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
		BufferedInputStream bis = new BufferedInputStream(bais);
		try {
			return this.xStream.fromXML(bis);
		} finally {
			try {
				bis.close();
			} catch (IOException ex) {
				throw ex;
			}
			try {
				bais.close();
			} catch (IOException ex) {
				throw ex;
			}
		}
	}
}
